package com.basker.pisces.core.meta;

import java.util.Collection;
import java.util.Set;

import com.basker.pisces.core.enums.DataObjectState;
import com.basker.pisces.core.exception.ReadOnlyObjectModifyException;
import com.basker.pisces.core.meta.annotation.TimestampField.TimestampType;

/**
 * 数据对象的元信息，主要描述了一个对象结构
 *
 * @author hangwen
 */
public interface IDataObjectMeta {

    /**
     * 是否包含指定字段
     *
     * @param name 字段名称，{@link IField#getName()}
     * @return
     */
    boolean containsField(String name);

    /**
     * 创建一个业务对象
     *
     * @return
     */
    Object createDataObject();

    /**
     * 获取代码字段
     *
     * @return
     */
    IDataField getCodeField();

    /**
     * 获取所有集合类型的字段
     *
     * @return
     */
    Collection<ICollectionField> getCollectionFields();

    /**
     * 获取所有数据字段
     *
     * @return
     */
    Collection<IDataField> getDataFields();

    /**
     * 获取对象的所属类
     *
     * @return
     */
    Class<?> getDataObjectClass();

    /**
     * 获取对象字段集合
     *
     * @return
     */
    Collection<IDataObjectField> getDataObjectFields();

    /**
     * 显示名称
     *
     * @return
     */
    String getDisplayName();

    /**
     * 获取指定名称的字段，找不到返回null
     *
     * @param name 字段名称，{@link IField#getName()}
     * @return
     */
    IField getField(String name);

    /**
     * 获取所有字段的名称
     *
     * @return
     */
    Set<String> getFieldNames();

    /**
     * 获取所有字段
     *
     * @return
     */
    Collection<IField> getFields();

    /**
     * 获取所有索引字段
     *
     * @return
     */
    Collection<IDataField> getIndexFields();

    /**
     * 获取字段名称，同一个元信息中，字段名称是唯一的
     *
     * @return
     */
    String getName();

    /**
     * 获取名称字段
     *
     * @return
     */
    IDataField getNameField();

    /**
     * 获取对象某一字段的旧值，如果没有更改过，返回null
     *
     * @param dataObject
     * @param dataField
     * @return
     */
    Object getOldValue(Object dataObject, IDataField dataField);

    /**
     * 获取主键字段
     *
     * @return
     */
    IDataField getPkField();

    /**
     * 获取所有引用类型的字段（外键字段）
     *
     * @return
     */
    Collection<IReferenceField> getReferenceFields();

    /**
     * 获取所属对象所在的schema,不同schema的对象属于不同的数据库，为空则指向默认数据库。 schema的名称要和数据源的名称一致
     *
     * @return
     */
    String getSchema();

    /**
     * 获取指定对象的数据状态
     *
     * @param dataObject
     * @return
     */
    DataObjectState getState(Object dataObject);

    /**
     * 获取元信息的一对一扩展表，尚未实现
     *
     * @return
     */
    String[] getSubTableNames();

    /**
     * 获取元信息关联的数据表
     *
     * @return
     */
    String getTableName();

    /**
     * 获取时间戳字段
     *
     * @return
     */
    IDataField getTimestampField();

    /**
     * 时间戳的类型
     *
     * @return
     */
    TimestampType getTimestampType();

    /**
     * 判断对象的指定字段的值是否修改过
     *
     * @param dataObject
     * @param dataField
     * @return
     */
    boolean isChanged(Object dataObject, IDataField dataField);

    /**
     * 判断对象是否是从数据库加载的
     *
     * @param dataObject
     * @return
     */
    boolean isFromDB(Object dataObject);

    /**
     * 判断对象的扩展表的部分是否从数据库加载的 尚未实现
     *
     * @param dataObject
     * @param subTableName
     * @return
     */
    boolean isFromDB(Object dataObject, String subTableName);

    /**
     * 是否只读，只读元信息创建的对象也是只读的，一旦编辑会{@link ReadOnlyObjectModifyException}异常
     *
     * @return
     */
    boolean isReadOnly();

    /**
     * 设置对象是从数据库加载的
     *
     * @param dataObject
     */
    void setFromDB(Object dataObject);

    /**
     * 设置对象的扩展表部门是从数据库加载的 尚未实现
     *
     * @param dataObject
     */
    void setFromDB(Object dataObject, String subTableName);

    /**
     * 设置对象的数据状态
     *
     * @param dataObject
     * @param state
     */
    void setState(Object dataObject, DataObjectState state);

}
